package com.mycode.chapter03.stream;


import com.mycode.chapter03.connector.http.Constants;
import com.mycode.chapter03.connector.http.HttpRequest;
import org.apache.catalina.util.StringManager;

import javax.servlet.ServletInputStream;
import java.io.IOException;
import java.io.InputStream;

// Request 输入流
public class RequestStream extends ServletInputStream {

    // 管道是否关闭
    protected boolean closed = false;

    // 输入流准备好返回的字节数
    protected int count = 0;

    // 超过文本长度的内容 将不会读取，默认是 -1
    protected int length = -1;

    protected static StringManager sm = StringManager.getManager(Constants.Package);

    // 数据源的输入流
    protected InputStream stream = null;

    // 构建与请求相关联的 Servlet 输入流
    public RequestStream(HttpRequest request) {
        super();
        closed = false;
        count = 0;
        length = request.getContentLength();
        stream = request.getStream();
    }

    // 关闭输入流
    @Override
    public void close() throws IOException {
        if (closed) {
            throw new IOException(sm.getString("requestStream.close.closed"));
        }
        if (length > 0) {
            while (count < length) {
                int read = read();
                if (read < 0) {
                    break;
                }
            }
        }

        closed = true;
    }

    // 从数据输入流中读取指定长度的数据
    @Override
    public int read() throws IOException {
        // 判断流是否已经关闭
        if (closed) {
            throw new IOException(sm.getString("requestStream.read.closed"));
        }
        // 是否尚未有字节待读取
        if (length > 0 && count >= length) {
            return -1;
        }
        // 读取 并 计算下一个字节
        int read = stream.read();
        if (read >= 0) {
            count++;
        }
        return read;
    }

    @Override
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    @Override
    public int read(byte b[], int off, int len) throws IOException {
        int toRead = len;
        if (length > 0) {
            if (count >= length) {
                return -1;
            }
            if ((count + len) > length) {
                toRead = length - count;
            }
        }
        return super.read(b, off, toRead);
    }

}
